home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-12-10 | 27.9 KB | 857 lines |
- Syntax10.Scn.Fnt
- StampElems
- Alloc
- 10 Dec 95
- MODULE OPV;
- (* Control Module for the backend of the Oberon-2-Compiler for Sun-3.
- Diplomarbeit Samuel Urech
- Date: 30.10.92 Current version:
- IMPORT OPT, OPC, OPL, OPM;
- CONST
- (* object modes *)
- Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7;
- SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13;
- (* opcodes *)
- ASh = 0; LSh = 1; ROt = 3;
- (* Condition codes *)
- false = 1; true = 0;
- CC = 4; CS = 5; EQ = 7; GE = 12; GT = 14; HI = 2; LE = 15;
- LS = 3; LT = 13; MI = 11; NE = 6; PL = 10; VC = 8; VS = 9;
- (* operation node subclasses *)
- times = 1; slash = 2; div = 3; mod = 4;
- and = 5; plus = 6; minus = 7; or = 8; eql = 9;
- neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
- in = 15; is = 16; ash = 17; msk = 18; len = 19;
- conv = 20; abs = 21; cap = 22; odd = 23; not = 33;
- (* SYSTEM *)
- adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29;
- (* structure forms *)
- Undef = 0; Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6;
- Real = 7; LReal = 8; Set = 9; String = 10; NilTyp = 11; NoTyp = 12;
- Pointer = 13; ProcTyp = 14; Comp = 15;
- (* composite structure forms *)
- Basic = 1; Array = 2; DynArr = 3; Record = 4;
- intSet = { SInt, Int, LInt }; realSet = { Real, LReal };
- (* node classes *)
- Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
- Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
- Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
- Nifelse =20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
- Nreturn = 26; Nwith = 27; Ntrap = 28;
- (* function numbers *)
- assign = 0; newfn = 1; incfn = 13; decfn = 14;
- inclfn = 15; exclfn = 16; copyfn = 18; assertfn = 32;
- (* SYSTEM function numbers *)
- getfn = 24; putfn = 25; getrfn = 26; putrfn = 27; sysnewfn = 30; movefn = 31;
- VarParSize = OPM.PointerSize;
- RecVarParSize = 2 * OPM.PointerSize;
- ProcOff = 8;
- (* procedure flags *)
- hasBody = 1; isRedef = 2;
- (* accessibility of objects *)
- internal = 0; external = 1; externalR = 2;
- (* trap numbers *)
- WithTrap = 15;
- CaseTrap = 16;
- FuncTrap = 17;
- VAR assert, findpc, typCheck : BOOLEAN;
- loopEnd : OPL.Label;
- PROCEDURE Init*( opt : SET; bpc : LONGINT );
- CONST ass = 7; fpc = 8; typchk = 3;
- BEGIN
- typCheck := typchk IN opt;
- assert := ass IN opt;
- findpc := fpc IN opt;
- IF findpc THEN OPM.breakpc := bpc ELSE OPM.breakpc := MAX( LONGINT ) END
- END Init;
- PROCEDURE Base( typ : OPT.Struct ) : INTEGER;
- (* Returns the alignment of a type. *)
- BEGIN
- WHILE typ.comp = Array DO typ := typ.BaseTyp END;
- IF typ.form IN { Byte, Bool, Char, SInt } THEN RETURN 1
- ELSE RETURN 2
- END
- END Base;
- PROCEDURE Align( VAR adr : LONGINT; base : LONGINT );
- (* Aligns the given address with the given base. *)
- BEGIN
- IF adr > 0 THEN
- INC( adr, ( -adr ) MOD base );
- ELSE
- DEC( adr, adr MOD base );
- END;
- END Align;
- PROCEDURE ^TypSize*( typ : OPT.Struct; dummy : BOOLEAN );
- PROCEDURE ParamAdr( par : OPT.Object; VAR psize : LONGINT );
- (* Calculates the sizes of the parameters of a procedure and returns their sum in psize. *)
- VAR typ : OPT.Struct;
- c : INTEGER;
- BEGIN (* ParamAdr *)
- WHILE par # NIL DO
- typ := par.typ; c := typ.comp;
- TypSize( typ, FALSE );
- IF par.mode = VarPar THEN
- par.adr := psize;
- IF c = Record THEN INC( psize, RecVarParSize )
- ELSIF c = DynArr THEN INC( psize, typ.size )
- ELSE INC( psize, VarParSize )
- END;
- ELSE
- IF typ.form IN {Byte, Bool, Char, SInt, Int} THEN
- INC( psize, OPM.LIntSize );
- ELSE
- INC( psize, typ.size );
- END;
- par.adr := psize - typ.size;
- par.linkadr := par.adr;
- END; (* IF *)
- Align( psize, 4 ); (* all parameters are aligned to 4 bytes. *)
- par := par.link;
- END; (* WHILE *)
- END ParamAdr;
- PROCEDURE ^VarAdr( var : OPT.Object; VAR dsize : LONGINT );
- PROCEDURE ^Traverse( obj : OPT.Object; exported : BOOLEAN );
- PROCEDURE ProcSize( obj : OPT.Object; firstpass : BOOLEAN );
- (* Writes the size of the local variables into the field obj.conval.intval and calculates the addresses of all parameters. *)
- VAR oldPos : LONGINT;
- conval: OPT.Const;
- typ : OPT.Struct;
- redef : OPT.Object;
- BEGIN (* ProcSize *)
- conval := obj.conval;
- oldPos := OPM.errpos;
- OPM.errpos := obj.scope.adr;
- IF ( ( obj.vis # internal ) = firstpass ) OR ( obj.mode = TProc ) THEN
- obj.adr := -1;
- obj.linkadr := OPL.NewLabel;
- IF obj.mode IN { XProc, IProc, TProc } THEN
- IF OPL.entno < OPL.MaxEntry THEN
- obj.adr := OPL.entno;
- INC( OPL.entno );
- ELSE
- OPM.err( 226 );
- obj.adr := 1;
- END;
- END;
- IF obj.mnolev > 0 THEN
- conval.intval2 := ProcOff + OPM.PointerSize; (* for static link *)
- ELSE
- conval.intval2 := ProcOff;
- END;
- ParamAdr( obj.link, conval.intval2 );
- IF obj.mode = TProc THEN
- typ := obj.link.typ;
- IF typ.form = Pointer THEN typ := typ.BaseTyp END;
- OPT.FindField( obj.name, typ.BaseTyp, redef );
- IF redef # NIL THEN
- obj.adr := 10000H * ( redef.adr DIV 10000H ) (* mthno *) + obj.adr (* entno *);
- IF ~( isRedef IN obj.conval.setval ) THEN OPM.err( 134 ) END;
- ELSE
- INC( obj.adr, 10000H * typ.n );
- INC( typ.n );
- END; (* IF *)
- END; (* IF *)
- END; (* IF *)
- IF ~firstpass THEN
- IF ~( hasBody IN conval.setval ) THEN OPM.err( 129 ) END;
- conval.intval := 0;
- VarAdr( obj.scope.scope, conval.intval ); (* local variables *)
- Traverse( obj.scope.right, FALSE ); (* local types and procedures *)
- END;
- OPM.errpos := oldPos
- END ProcSize;
- PROCEDURE TypSize*( typ : OPT.Struct; dummy : BOOLEAN );
- (* Writes the size of a type into typ.size. All subordinate type sizes are calculated, all record fields get an offset. *)
- VAR offset, size : LONGINT;
- fld : OPT.Object;
- btyp : OPT.Struct;
- BEGIN (* TypSize *)
- IF typ.size = -1 THEN
- CASE typ.form OF
- Pointer :
- typ.size := OPM.PointerSize;
- IF typ.BaseTyp = OPT.undftyp THEN
- OPM.Mark( 128, typ.n );
- ELSE
- TypSize( typ.BaseTyp, FALSE );
- END;
- | ProcTyp :
- size := ProcOff; typ.size := OPM.ProcSize;
- ParamAdr( typ.link, size ); (* inserts the addresses of the parameters. *)
- | Comp :
- CASE typ.comp OF
- Record :
- btyp := typ.BaseTyp;
- IF btyp = NIL THEN
- offset := 0;
- ELSE
- TypSize( btyp, FALSE );
- offset := btyp.size;
- END;
- fld := typ.link;
- WHILE ( fld # NIL ) & ( fld.mode = Fld ) DO
- btyp := fld.typ;
- TypSize( btyp, FALSE );
- size := btyp.size;
- Align( offset, Base( btyp ) );
- fld.adr := offset;
- INC( offset, size );
- fld := fld.link
- END; (* WHILE *)
- Align( offset, 2 ); (* all records are at least 2 Bytes long *)
- typ.size := offset;
- | Array :
- TypSize( typ.BaseTyp, FALSE );
- typ.size := typ.n * typ.BaseTyp.size;
- | DynArr :
- btyp := typ.BaseTyp;
- IF typ.offset < 0 THEN typ.offset := typ.n; END;
- IF btyp.comp = DynArr THEN btyp.offset := typ.n; END;
- TypSize( btyp, FALSE );
- IF btyp.comp = DynArr THEN
- typ.size := btyp.size + 4;
- ELSE
- typ.size := 8;
- END;
- END; (* CASE *)
- ELSE (* nothing *)
- END; (* CASE typ.form *)
- END; (* IF *)
- END TypSize;
- PROCEDURE VarAdr( var : OPT.Object; VAR dsize : LONGINT );
- (* Inserts entry-numbers and addresses into the variables. Exported variables are entered into the entry list. *)
- VAR typ: OPT.Struct; adr: LONGINT;
- BEGIN
- adr := -dsize;
- WHILE var # NIL DO
- typ := var.typ;
- TypSize( typ, FALSE );
- DEC( adr, typ.size );
- IF typ.form = Comp THEN
- Align( adr, 4 );
- ELSE
- Align( adr, Base( typ ) );
- END; (* IF *)
- IF var.vis = internal THEN
- var.adr := adr;
- ELSE
- OPL.SetEntry( OPL.entno, adr );
- var.adr := OPL.entno;
- INC( OPL.entno );
- END; (* IF *)
- var.linkadr := adr;
- var := var.link
- END; (* WHILE *)
- dsize := -adr;
- Align( dsize, 8 );
- END VarAdr;
- PROCEDURE Traverse( obj : OPT.Object; exported : BOOLEAN );
- (* Completes types and procedures. *)
- VAR typ: OPT.Struct;
- PROCEDURE TraverseRecord( typ : OPT.Struct );
- (* Inserts the type descriptor address into the types and the method numbers into the methods. *)
- BEGIN
- IF typ.tdadr = OPM.TDAdrUndef THEN
- IF typ.BaseTyp # NIL THEN
- TraverseRecord( typ.BaseTyp );
- typ.n := typ.BaseTyp.n;
- END; (* IF *)
- Traverse( typ.link, FALSE ); (* traverse methods *)
- OPL.AllocTypDesc( typ );
- END; (* IF *)
- END TraverseRecord;
- BEGIN (* Traverse *)
- IF obj # NIL THEN
- Traverse( obj.left, exported );
- IF ( obj.mode = Typ ) & ( ( obj.vis # internal ) = exported ) THEN
- typ := obj.typ;
- TypSize( typ, FALSE );
- IF typ.form = Pointer THEN typ := typ.BaseTyp END;
- IF typ.comp = Record THEN TraverseRecord( typ ) END;
- ELSIF obj.mode IN {LProc, XProc, TProc, CProc, IProc} THEN
- ProcSize( obj, exported )
- END ;
- Traverse( obj.right, exported )
- END
- END Traverse;
- PROCEDURE AdrAndSize*;
- (* Completes the symbol table: types, variables, record-fields and procedures. *)
- BEGIN (* AdrAndSize *)
- OPL.dsize := 0;
- VarAdr( OPT.topScope.scope, OPL.dsize );
- OPM.errpos := OPT.topScope.adr; (* text position of the scope *)
- Traverse( OPT.topScope.right, TRUE ); (* first run for all exported types and procedures *)
- Traverse( OPT.topScope.right, FALSE ); (* second run for all local types and procedures *)
- END AdrAndSize;
- PROCEDURE BaseTyp( typ : OPT.Struct ) : OPT.Struct;
- (* Returns the record type belonging to typ. *)
- BEGIN (* BaseTyp *)
- IF typ.form = Pointer THEN RETURN typ.BaseTyp
- ELSE RETURN typ
- END
- END BaseTyp;
- PROCEDURE ^Expr( node : OPT.Node; VAR res : OPL.Item );
- PROCEDURE Designator( node : OPT.Node; VAR res : OPL.Item );
- (* Returns an item for a designator. res.mode is in { regx, pcx }. *)
- VAR index, tag : OPL.Item;
- BEGIN (* Designator *)
- CASE node.class OF
- Nvar, Nvarpar :
- OPC.MakeVar( node.obj, res );
- | Nfield :
- Designator( node.left, res );
- OPC.MakeField( res, node.obj.adr, node.typ );
- | Nderef :
- Designator( node.left, res );
- OPC.DeRef( node.typ, res );
- | Nindex :
- Expr( node.right, index );
- Designator( node.left, res );
- OPC.MakeIndex( index, res );
- | Nguard, Neguard :
- Designator( node.left, res );
- IF typCheck THEN
- OPC.saveRegs:=FALSE;
- OPC.MakeTag( node.left.obj, node.left.typ, res, tag );
- OPC.TypeTest( tag, BaseTyp( node.typ ), TRUE, node.class = Neguard );
- OPC.saveRegs:=TRUE;
- END; (* IF *)
- | Nproc :
- OPC.MakeProc( node.obj, node.subcl, res );
- END; (* CASE *)
- res.typ := node.typ;
- END Designator;
- PROCEDURE AllocParams( formalPar : OPT.Object; VAR psize : LONGINT );
- (* Allocates space on the stack for the parameters and increments psize by their size. *)
- BEGIN (* AllocParams *)
- WHILE formalPar # NIL DO
- IF formalPar.mode = VarPar THEN
- IF formalPar.typ.comp = Record THEN INC( psize, RecVarParSize )
- ELSIF formalPar.typ.comp = DynArr THEN INC( psize, formalPar.typ.size )
- ELSE INC( psize, VarParSize )
- END;
- ELSE
- INC( psize, formalPar.typ.size );
- END; (* IF *)
- Align( psize, 4 );
- formalPar := formalPar.link;
- END; (* WHILE *)
- OPC.AddToSP( -psize );
- END AllocParams;
- PROCEDURE AssignParams( formalPar : OPT.Object; actualPar : OPT.Node );
- (* Moves the actual parameters to the stack. *)
- VAR par, par1, tag : OPL.Item;
- BEGIN (* AssignParams *)
- WHILE formalPar # NIL DO
- IF formalPar.typ.comp = DynArr THEN
- Expr( actualPar, par );
- OPC.MoveDynArrStack( formalPar.typ, formalPar.adr - ProcOff, par );
- ELSIF formalPar.mode = VarPar THEN
- Designator( actualPar, par );
- par1 := par;
- OPC.MoveAdrStack( formalPar.adr - ProcOff, par );
- IF formalPar.typ.comp = Record THEN
- OPC.MakeTag( actualPar.obj, actualPar.typ, par, tag );
- OPC.MoveStack( formalPar.adr + 4 - ProcOff, tag );
- ELSIF ( formalPar.typ = OPT.sysptrtyp ) & ( actualPar.typ # OPT.sysptrtyp ) THEN
- (* pass static type to enable run time tests *)
- OPC.StaticTag( actualPar.typ.BaseTyp, tag );
- OPC.Assign( tag, par1 );
- ELSIF ( formalPar.typ = OPT.sysptrtyp ) & ( actualPar.typ = OPT.sysptrtyp ) & ( actualPar.obj.mode # VarPar ) THEN
- (* pass NIL to disable run time tests *)
- OPC.MakeIntConst( 0, OPT.linttyp, tag );
- OPC.Assign( tag, par1 );
- END; (* IF *)
- ELSE
- par.tJump := OPL.NewLabel;
- par.fJump := OPL.NewLabel;
- Expr( actualPar, par );
- OPC.Convert( par, formalPar.typ );
- OPC.MoveStack( formalPar.adr - ProcOff, par );
- END; (* IF *)
- OPL.usedRegs := { };
- actualPar := actualPar.link;
- formalPar := formalPar.link;
- END; (* WHILE *)
- END AssignParams;
- PROCEDURE Expr( node : OPT.Node; VAR res : OPL.Item );
- (* Returns an item for the result of an exression. *)
- VAR expr1, expr2, expression, set, element, procItem, arr, tag : OPL.Item;
- swap : OPL.Label;
- savedRegs : SET;
- psize : LONGINT;
- BEGIN (* Expr *)
- CASE node.class OF
- Nconst :
- OPC.MakeConst( node.obj, node.conval, node.typ, res );
- | Nupto :
- Expr( node.left, expr1 );
- Expr( node.right, expr2 );
- OPC.UpTo( expr1, expr2, res );
- | Nmop :
- CASE node.subcl OF
- not :
- swap := res.tJump;
- res.tJump := res.fJump;
- res.fJump := swap;
- Expr( node.left, res );
- swap := res.tJump;
- res.tJump := res.fJump;
- res.fJump := swap;
- OPC.Not( res );
- | minus :
- Expr( node.left, res );
- OPC.Neg( res );
- | is :
- Designator( node.left, res );
- tag.tJump := res.tJump;
- tag.fJump := res.fJump;
- OPC.saveRegs:=FALSE;
- OPC.MakeTag( node.left.obj, node.left.typ, res, tag );
- OPC.TypeTest( tag, BaseTyp( node.obj.typ ), FALSE, FALSE );
- OPC.saveRegs:=TRUE;
- res := tag;
- | conv :
- Expr( node.left, res );
- IF node.typ.form = Set THEN
- OPC.SetElem( res );
- ELSE
- OPC.Convert( res, node.typ );
- END; (* IF *)
- | abs :
- Expr( node.left, res );
- OPC.Abs( res );
- | cap :
- Expr( node.left, res );
- OPC.Cap( res );
- | odd :
- Expr( node.left, res );
- OPC.Odd( res );
- | adr :
- Expr( node.left, res );
- OPC.Adr( res );
- | cc :
- OPC.MakeCocItem( SHORT( node.left.conval.intval ), res );
- | val :
- res.tJump := OPL.NewLabel;
- res.fJump := OPL.NewLabel;
- Expr( node.left, res );
- IF res.typ.comp = DynArr THEN OPC.GetDynArrVal( res ); END;
- res.typ := node.typ;
- END; (* CASE *)
- | Ndop :
- CASE node.subcl OF
- times :
- Expr( node.left, expression );
- Expr( node.right, res );
- OPC.Mul( node.typ, expression, res );
- | slash :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Divide( node.typ, expression, res );
- | div :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Div( expression, res );
- | mod :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Mod( expression, res );
- | and :
- savedRegs := OPL.usedRegs;
- expression.tJump := OPL.NewLabel;
- expression.fJump := res.fJump;
- Expr( node.left, expression );
- OPC.FalseJump( expression, expression.fJump );
- OPL.usedRegs := savedRegs;
- Expr( node.right, res );
- OPC.Test( res );
- res.fJump := OPL.MergedLinks( expression.fJump, res.fJump );
- | plus :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Plus( node.typ, expression, res );
- | minus :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Minus( node.typ, expression, res );
- | or :
- savedRegs := OPL.usedRegs;
- expression.tJump := res.tJump;
- expression.fJump := OPL.NewLabel;
- Expr( node.left, expression );
- OPC.TrueJump( expression, expression.tJump );
- OPL.usedRegs := savedRegs;
- Expr( node.right, res );
- OPC.Test( res );
- res.tJump := OPL.MergedLinks( expression.tJump, res.tJump );
- | eql, neq, lss, leq, gtr, geq :
- expr1.tJump := OPL.NewLabel;
- expr1.fJump := OPL.NewLabel;
- expr2.tJump := OPL.NewLabel;
- expr2.fJump := OPL.NewLabel;
- Expr( node.left, expr1 );
- OPC.LoadCC( expr1 );
- Expr( node.right, expr2 );
- OPC.Compare( node.subcl, expr1, expr2, res );
- | in :
- Expr( node.left, element );
- Expr( node.right, set );
- OPC.In( element, set, res );
- | ash :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Shift( ASh, expression, res );
- | msk :
- Expr( node.left, res );
- OPC.Mask( -node.right.conval.intval-1, res );
- | len :
- Designator( node.left, arr );
- OPC.MakeLen( arr, node.right.conval.intval, res );
- | bit :
- Expr( node.left, expr1 );
- Expr( node.right, expr2 );
- OPC.SYSBit( expr1, expr2, res );
- | lsh :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Shift( LSh, expression, res );
- | rot :
- Expr( node.left, res );
- Expr( node.right, expression );
- OPC.Shift( ROt, expression, res );
- END; (* CASE *)
- | Ncall :
- savedRegs := OPL.usedRegs;
- OPC.PushRegs( OPL.usedRegs );
- OPL.usedRegs := { };
- IF ( node.left.obj # NIL ) & ( node.left.obj.mode = LProc ) & ( node.left.obj.mnolev > 0 ) THEN
- psize := OPM.PointerSize; (* for static link *)
- ELSE
- psize := 0;
- END;
- AllocParams( node.obj, psize );
- OPC.WriteStaticLink( node.left.obj );
- AssignParams( node.obj, node.right );
- Designator( node.left, procItem );
- OPC.Call( procItem, node.left.obj );
- OPC.AddToSP( psize );
- OPL.usedRegs := savedRegs;
- OPC.GetResult( node.left.typ, res );
- OPC.PopRegs( savedRegs );
- ELSE
- Designator( node, res );
- END; (* CASE *)
- res.typ := node.typ;
- END Expr;
- PROCEDURE Checkpc;
- BEGIN
- IF findpc & (OPL.pc > OPM.breakpc) & OPM.noerr THEN OPM.err(255) END
- (* in the case of a call, the breakpc value shown in the trap viewer must point to the call instruction
- and not to the next instruction, i.e. breakpc # return address !! *)
- END Checkpc;
- PROCEDURE StatSeq( node : OPT.Node );
- (* Generates code for a statement sequence. *)
- VAR proc : OPT.Object;
- designator, expression, sourceAdr, destAdr, procItem, reg, tag : OPL.Item;
- begLabel, savedLoopEnd : OPL.Label;
- psize : LONGINT;
- PROCEDURE CaseStatement( node : OPT.Node );
- (* Generates code for a case statement. *)
- VAR expression : OPL.Item;
- lo, hi, i, jtAdr : LONGINT;
- elseLabel, endLabel : OPL.Label;
- case, caseLabel : OPT.Node;
- BEGIN (* CaseStatement *)
- Expr( node.left, expression );
- node := node.right;
- lo := node.conval.intval;
- hi := node.conval.intval2;
- IF hi >= lo THEN
- elseLabel := OPL.NewLabel;
- endLabel := OPL.NewLabel;
- OPC.Case( expression, lo, hi, elseLabel, jtAdr );
- FOR i := 0 TO hi - lo DO OPL.ConstWord( SHORT( jtAdr + 2 * i ), OPL.pc DIV 2 ); END;
- OPL.DefineLabel( elseLabel );
- END; (* IF *)
- Checkpc;
- IF node.conval.setval = { } THEN
- OPC.Trap( CaseTrap );
- ELSE
- StatSeq( node.right );
- END;
- IF hi >= lo THEN
- case := node.left;
- WHILE case # NIL DO
- OPL.Jump( true, endLabel );
- caseLabel := case.left;
- WHILE caseLabel # NIL DO
- FOR i := caseLabel.conval.intval - lo TO caseLabel.conval.intval2 - lo DO
- OPL.ConstWord( SHORT( jtAdr + 2 * i ), OPL.pc DIV 2 );
- END; (* FOR *)
- caseLabel := caseLabel.link;
- END; (* WHILE *)
- StatSeq( case.right );
- case := case.link;
- END; (* WHILE *)
- OPL.DefineLabel( endLabel );
- END; (* IF *)
- END CaseStatement;
- PROCEDURE IfStatement( node : OPT.Node; trap : BOOLEAN );
- (* Generates code for an IF-Statement. If trap is true, a Trap is generated in the ELSE-Case. *)
- VAR endLabel : OPL.Label;
- curNode : OPT.Node;
- expression : OPL.Item;
- BEGIN (* IfStatement *)
- endLabel := OPL.NewLabel;
- curNode := node.left;
- WHILE curNode # NIL DO
- expression.tJump := OPL.NewLabel;
- expression.fJump := OPL.NewLabel;
- Expr( curNode.left, expression );
- OPC.FalseJump( expression, expression.fJump ); Checkpc;
- StatSeq( curNode.right );
- IF ( curNode.link # NIL ) OR ( node.right # NIL ) OR trap THEN
- (* last ELSIF part with no ELSE following *)
- OPL.Jump( true, endLabel );
- END;
- OPL.DefineLabel( expression.fJump );
- curNode := curNode.link;
- END; (* WHILE *)
- IF trap THEN
- OPC.Trap( WithTrap );
- ELSE
- StatSeq( node.right );
- END; (* IF *)
- OPL.DefineLabel( endLabel );
- END IfStatement;
- PROCEDURE Size( typ : OPT.Struct; node : OPT.Node; VAR res : OPL.Item );
- (* Returns an item that denotes the size of the memory space in bytes that has to be allocated for a dynamic array. *)
- VAR dim, offsetItem : OPL.Item;
- noflen : INTEGER;
- BEGIN (* Size *)
- Expr( node, res );
- noflen := 1;
- node := node.link;
- typ := typ.BaseTyp.BaseTyp;
- WHILE node # NIL DO
- Expr( node, dim );
- INC( noflen );
- OPC.Mul( OPT.linttyp, dim, res );
- node := node.link;
- typ := typ.BaseTyp;
- END; (* WHILE *)
- IF typ.size > 1 THEN
- OPC.MakeIntConst( typ.size, OPT.linttyp, dim );
- OPC.Mul( OPT.linttyp, dim, res );
- END; (* IF *)
- OPC.MakeIntConst( 4 * noflen, OPT.linttyp, offsetItem );
- OPC.Plus( OPT.linttyp, offsetItem, res );
- END Size;
- PROCEDURE EnterLengths( VAR item : OPL.Item; node : OPT.Node );
- (* Writes the lengths in node to the address in item. Used for NEW( p, len1, len2, ... ). *)
- VAR length, adr : OPL.Item;
- BEGIN (* EnterLengths *)
- adr := item;
- OPC.DeRef( OPT.sysptrtyp, adr );
- WHILE node # NIL DO
- Expr( node, length );
- OPC.Convert( length, OPT.linttyp );
- OPL.Move( length, adr );
- INC( adr.bd, 4 );
- node := node.link;
- END; (* WHILE *)
- END EnterLengths;
- PROCEDURE Prepend( s : ARRAY OF CHAR );
- (* Writes the given name in parentheses to the reference file. *)
- VAR i : INTEGER;
- ch : CHAR;
- BEGIN (* Prepend *)
- i := 0;
- ch := s[ 0 ];
- OPM.RefW( "(" );
- WHILE ch # 0X DO
- OPM.RefW( ch );
- INC( i );
- ch := s[ i ];
- END; (* WHILE *)
- OPM.RefW( ")" );
- END Prepend;
- BEGIN (* StatSeq *)
- WHILE ( node # NIL ) & OPM.noerr DO
- OPM.errpos := node.conval.intval;
- OPL.BegStat;
- CASE node.class OF
- Nenter :
- IF node.obj = NIL THEN (* module *)
- OPC.EnterMod;
- StatSeq( node.right );
- OPC.Return( NIL, FALSE, expression );
- OPL.OutRefPoint;
- OPL.OutRefName( "$" );
- OPL.OutRefs( OPT.topScope );
- INC( OPL.level );
- StatSeq( node.left );
- DEC( OPL.level );
- ELSE (* procedure *)
- proc := node.obj;
- INC( OPL.level );
- StatSeq( node.left );
- DEC( OPL.level );
- OPC.EnterProc( proc );
- StatSeq( node.right );
- IF proc.typ # OPT.notyp THEN OPC.Trap( FuncTrap );
- ELSE OPC.Return( proc, FALSE, expression );
- END;
- OPL.OutRefPoint;
- IF proc^.mode = TProc THEN Prepend( proc^.link^.typ^.strobj^.name ) END;
- OPL.OutRefName( proc^.name );
- OPL.OutRefs( proc^.scope^.right );
- END; (* IF *)
- | Ninittd :
- | Nassign :
- CASE node.subcl OF
- assign :
- expression.tJump := OPL.NewLabel;
- expression.fJump := OPL.NewLabel;
- Expr( node.right, expression );
- OPC.LoadCC( expression );
- Designator( node.left, designator );
- OPC.Assign( expression, designator );
- | newfn :
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- IF node.right = NIL THEN
- IF node.left.typ.BaseTyp.comp = Record THEN
- OPC.StaticTag( node.left.typ.BaseTyp, tag );
- OPC.New( designator, tag );
- ELSE
- OPC.MakeIntConst( node.left.typ.BaseTyp.size, OPT.linttyp, expression );
- OPC.SYSNew( designator, expression );
- END; (* IF *)
- ELSE
- Size( node.left.typ, node.right, expression );
- OPC.SYSNew( designator, expression );
- EnterLengths( designator, node.right );
- END; (* IF *)
- | incfn :
- Expr( node.right, expression );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.Increment( designator, expression );
- | decfn :
- Expr( node.right, expression );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.Decrement( designator, expression );
- | inclfn :
- Expr( node.right, expression );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.Include( designator, expression );
- | exclfn :
- Expr( node.right, expression );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.Exclude( designator, expression );
- | copyfn :
- Expr( node.right, expression );
- Designator( node.left, designator );
- OPC.Copy( expression, designator );
- | getfn :
- Expr( node.right, sourceAdr );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.SYSGet( sourceAdr, designator );
- | putfn :
- Expr( node.left, destAdr );
- Expr( node.right, expression );
- OPC.SYSPut( expression, destAdr );
- | getrfn :
- OPC.MakeConst( node.obj, node.right.conval, OPT.inttyp, reg );
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- OPC.SYSGetReg( designator, reg );
- | putrfn :
- OPC.MakeConst( node.obj, node.left.conval, OPT.inttyp, reg );
- Expr( node.right, expression );
- OPC.SYSPutReg( expression, reg );
- | sysnewfn :
- Designator( node.left, designator );
- OPL.LoadAdr( designator );
- Expr( node.right, expression );
- OPC.SYSNew( designator, expression );
- | movefn :
- Expr( node.left, sourceAdr );
- Expr( node.right, destAdr );
- Expr( node.right.link, expression );
- OPC.SYSMove( destAdr, sourceAdr, expression );
- END; (* CASE *)
- | Ncall :
- IF ( node.left.obj # NIL ) & ( node.left.obj.mode = LProc ) & ( node.left.obj.mnolev > 0 ) THEN
- psize := OPM.PointerSize; (* for static link *)
- ELSE
- psize := 0;
- END;
- AllocParams( node.obj, psize );
- OPC.WriteStaticLink( node.left.obj );
- AssignParams( node.obj, node.right );
- Designator( node.left, procItem );
- OPC.Call( procItem, node.left.obj );
- OPC.AddToSP( psize );
- | Nifelse :
- IF ( node^.subcl # assertfn ) OR assert THEN IfStatement( node, FALSE ); END;
- | Ncase :
- CaseStatement( node );
- | Nwhile :
- begLabel := OPL.NewLabel;
- OPL.DefineLabel( begLabel );
- expression.tJump := OPL.NewLabel;
- expression.fJump := OPL.NewLabel;
- Expr( node.left, expression );
- OPC.FalseJump( expression, expression.fJump );
- StatSeq( node.right );
- OPL.Jump( true, begLabel );
- OPL.DefineLabel( expression.fJump );
- | Nrepeat :
- expression.tJump := OPL.NewLabel;
- expression.fJump := OPL.NewLabel;
- OPL.DefineLabel( expression.fJump );
- StatSeq( node.left );
- OPL.BegStat;
- Expr( node.right, expression );
- OPC.FalseJump( expression, expression.fJump );
- | Nloop :
- savedLoopEnd := loopEnd;
- begLabel := OPL.NewLabel;
- loopEnd := OPL.NewLabel;
- OPL.DefineLabel( begLabel );
- StatSeq( node.left );
- OPL.Jump( true, begLabel );
- OPL.DefineLabel( loopEnd );
- loopEnd := savedLoopEnd;
- | Nexit :
- OPL.Jump( true, loopEnd );
- | Nreturn :
- IF node.left # NIL THEN
- expression.tJump := OPL.NewLabel;
- expression.fJump := OPL.NewLabel;
- Expr( node.left, expression )
- END;
- OPC.Return( node.obj, node.left # NIL, expression );
- | Nwith :
- IfStatement( node, node.subcl = 0 );
- | Ntrap :
- IF node.right.conval.intval = 0 THEN node.right.conval.intval := 14 END ; (* should be parameter for front end*)
- OPC.Trap( SHORT( node.right.conval.intval ) );
- END; (* CASE *)
- Checkpc;
- node := node.link;
- END; (* WHILE *)
- END StatSeq;
- PROCEDURE Module*( prog : OPT.Node );
- BEGIN
- StatSeq( prog )
- END Module;
- END OPV.
-